package utils;

import interfacesFerrovia.DefsGlobais.TipoAtributo;
import malhaFerroviaria.Ferrovia;
import mc747.Composicao;

public class Utils {
	
	Ferrovia ferrovia = Ferrovia.getInstance();
	
	// Calcula o tempo de chegada de A ate B
	public int calculaTempoChegadaAB(float velocidadeAtual, float distancia) {
		
		Float tempoChegada;
		tempoChegada = distancia/velocidadeAtual;
		
		System.out.println("****dista "+distancia);
		System.out.println("****velo "+velocidadeAtual);
		System.out.println("tempoChe "+tempoChegada);
		System.out.println("tempoCheINT "+tempoChegada.intValue());
		return tempoChegada.intValue();
	}
	
	
	// Calcula distancia total que uma composicao deve percorrer
	public Float calculaDistanciaTotal(String idComposicao) {
		
		Float distanciaTotal = 0f;

		String itinerario[] = (String[]) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ITINERARIO);
		
		for(String s : itinerario) {
			String idChaveB = (String) ferrovia.consultaAtributo(s, TipoAtributo.ID_TR_CH_B);
			if (idChaveB != null) {
				distanciaTotal += (Float) ferrovia.consultaAtributo(idChaveB, TipoAtributo.DISTANCIA);	
			}
			
			distanciaTotal += (Float) ferrovia.consultaAtributo(s, TipoAtributo.DISTANCIA);
		}
		
		return distanciaTotal;
	}
	
	
	// Calcula frenagem necessaria para chegar em um determinado ponto (usado para parar uma composicao)
	public Float calculaFrenagem(String idComposicao, float velInicial, float velFinal, float distancia) {
		Float frenagem = 0f;
		
		frenagem = ((velFinal*velFinal) - (velInicial*velInicial))/(2*distancia);
		
		if (frenagem > (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.FRENAGEM_MAX)) {
			frenagem = (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.FRENAGEM_MAX);
		}
		
		return Math.abs(frenagem);
	}
	
	// Sorvetao
	public Float calculaFrenagemComposicao(String idComposicao, float velInicial, float tempo, float distancia) {
		Float frenagem = 0f;
		
		frenagem = (2*(distancia-(velInicial*tempo)))/(tempo*tempo);
		
		if (frenagem > (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.FRENAGEM_MAX)) {
			frenagem = (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.FRENAGEM_MAX);
		}
		
		return Math.abs(frenagem);
	}
	
	// Verifica trecho atual e proximo trecho que uma composicao ira entrar, para posicionar a chave corretamente
	public Boolean posicionaChave(String idComposicao, String idChave) {
		String idTrechoA = "";
		String idTrechoB = "";
		
		System.out.println("ENTROU POSICIONA CHAVE");
		
		idTrechoA = (String) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL);
		
		String itinerario[] = (String[]) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ITINERARIO);

		boolean aux = false;
		for(String s : itinerario) {
			if (aux){
				idTrechoB = s;
				break;
			}
			if (s.equalsIgnoreCase(idTrechoA))
				aux = true;	
		}
		
	//	if (!idTrechoA.equals("") && !idTrechoA.equals(null) && !idTrechoB.equals("")) {
		//	if (!idTrechoA.equalsIgnoreCase((String)ferrovia.consultaAtributo(idChave, TipoAtributo.ID_TR_CH_A)) &&
			//	 !idTrechoB.equalsIgnoreCase((String)ferrovia.consultaAtributo(idChave, TipoAtributo.ID_TR_CH_B))) {
	      if ((Boolean) ferrovia.consultaAtributo(idComposicao, TipoAtributo.SENTIDO_ATUAL) == true) {
				ferrovia.mudarChave(idChave, idTrechoA, idTrechoB);
	      } else {
				ferrovia.mudarChave(idChave, idTrechoB, idTrechoA);
	      }
				
				System.out.println("MudarChave: " + idChave + " - trechoA: " + idTrechoA + " - trechoB: " + idTrechoB);
			//}
			return true;
		//}
		
		//return false;
	}
	
	
	// Verifica se chave ira mudar a tempo da composicao chegar, retorna true se sim.
	public Boolean verificaTempoMudancaCh(String idChave, String idComposicao) {
		Float distanciaTotal = (Float) ferrovia.consultaAtributo((String)ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL), TipoAtributo.DISTANCIA);
		Float posAtual = (Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.POSICAO_ATUAL);
		int tempoChegadaComp;
		int tempoMudancaChave;
		
		tempoChegadaComp = calculaTempoChegadaAB((Float) ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL), distanciaTotal-posAtual);
		tempoMudancaChave = (Integer) ferrovia.consultaAtributo(idChave, TipoAtributo.TEMPO_MUDANCA);
		
		if (tempoChegadaComp > tempoMudancaChave) {
			return true;
		}
		
		return false;
	}
	
	
	// Verifica o ultimo trecho do itinerario de uma composicao
	public String verificaUltimoTrecho(String idComposicao) {
		
		String ultimoTrecho;

		String itinerario[] = (String[]) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ITINERARIO);
		
		int tamanho = itinerario.length;
		
		ultimoTrecho = itinerario[tamanho-1];
		
		return ultimoTrecho;
	}
	
	// v = vo + at
	public Float calculaVelFinal (Float velInicial, Float acel, int tempo) {
		Float velFinal;
		
		velFinal = velInicial + (acel * tempo);
		
		return velFinal;
	}

	// Verifica o proximo trecho do itinerario de uma composicao
	public String verificaProximoTrecho(String idComposicao) {
		
		String proximoTrecho = "";
		
		String itinerario[] = (String[]) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ITINERARIO);
		String trechoAtual = (String) ferrovia.consultaAtributo(idComposicao, TipoAtributo.ID_TR_CH_ATUAL);
		
		Boolean aux = false;
		for (String s : itinerario){
			if (aux){
				proximoTrecho = s;
				break;
			}
			if (s.equalsIgnoreCase(trechoAtual)){
				aux = true;
			}
		}
		
		return proximoTrecho;
	}

	public void frearComp(String idComposicao, String idTrecho, Float frenagem){
//			ferrovia.frearComposicao(idComposicao, 0, Boolean.TRUE);
			ferrovia.frearComposicao(idComposicao, 0f, frenagem);
	}
	
	//Calcula aceleracao para frear completamente no espaco restante
	public float acelFrenagem (String idTrecho, String idComposicao){
		Float velInicial = (Float)ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL);
		Float velFinal = 0f;
		Float distancia = getEspacoFrenagem(idTrecho, idComposicao) ;
		
		Float acelFrenagem = calculaFrenagem(idComposicao, velInicial, velFinal, distancia);
		return acelFrenagem;
	}
	
	//Calcula espaco que falta percorrer
	public Float getEspacoFrenagem(String idTrecho, String idComposicao){
		
		Float distancia = (Float)ferrovia.consultaAtributo(idTrecho, TipoAtributo.DISTANCIA);
		Float posAtual = (Float)ferrovia.consultaAtributo(idComposicao, TipoAtributo.POSICAO_ATUAL);
		Integer tamTrem = (Integer)ferrovia.consultaAtributo(idComposicao, TipoAtributo.COMPRIMENTO);
		
		Float espaco = Math.abs(distancia);
		return espaco;
	}
	
	
	public int verificaTicFrearChegada(String idTrecho, String idComposicao, int instanteAtual){

//		Float espaco = this.getEspacoFrenagem(idTrecho, idComposicao);
				
		Integer tamTrem = (Integer)ferrovia.consultaAtributo(idComposicao, TipoAtributo.COMPRIMENTO);
//		Integer tempoNec = calculaTempoChegadaAB((Float)ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL), espaco);

		Float distancia =  (Float)ferrovia.consultaAtributo(idTrecho, TipoAtributo.DISTANCIA);
		Float distMin = ferrovia.consultaDistMinParada(idComposicao);
		Integer ticRetorno = instanteAtual + ferrovia.consultaTempo(idComposicao, Math.abs(distMin-distancia) )/*calculaTempoChegadaAB((Float)ferrovia.consultaAtributo(idComposicao, TipoAtributo.VEL_ATUAL), distancia - distMin)*/;
	
		System.out.println("distancia - "+distancia);
		System.out.println("Dist MIN - "+distMin);
		System.out.println("ticRetorno - "+ticRetorno);
		System.out.println("tamTrem - "+tamTrem );
		
		
//		int ticRetorno = instanteAtual /*+ tempoNec*/;
		
//		System.out.println("tempo consulta "+ferrovia.consultaTempo(idComposicao, distancia - minDist));
//		System.out.println("tempo chegada "+ferrovia.consultaTempo(idComposicao, (Float)ferrovia.consultaAtributo(idTrecho, TipoAtributo.DISTANCIA)));
		
		
//		ferrovia.consultaPosicao(idComposicao, instante)
		
		
		
		return ticRetorno;
	}
	
	// compara o tempo de chegada de composicoes a have
	public int comparaTempoChegadaChave(String idComp1, String idComp2){		
		Utils u = new Utils();
		String idTrechoComp1 = (String) ferrovia.consultaAtributo(idComp1, TipoAtributo.ID_TR_CH_ATUAL);
		String idTrechoComp2 = (String) ferrovia.consultaAtributo(idComp2, TipoAtributo.ID_TR_CH_ATUAL);
		Float velAtualComp1 = (Float) ferrovia.consultaAtributo(idComp1, TipoAtributo.VEL_ATUAL);
		Float velAtualComp2 = (Float) ferrovia.consultaAtributo(idComp2, TipoAtributo.VEL_ATUAL);
		Float distComp1Chave;
		Float distComp2Chave;
		int t1;
		int t2;

		
		if((Boolean)ferrovia.consultaAtributo(idComp1, TipoAtributo.SENTIDO_ATUAL)) {
			distComp1Chave = (Float)ferrovia.consultaAtributo(idTrechoComp1, TipoAtributo.COMPRIMENTO) - (Float)ferrovia.consultaAtributo(idComp1, TipoAtributo.POSICAO_ATUAL);
		} else {
			distComp1Chave = (Float)ferrovia.consultaAtributo(idComp1, TipoAtributo.POSICAO_ATUAL);
		}
		
		if((Boolean)ferrovia.consultaAtributo(idComp2, TipoAtributo.SENTIDO_ATUAL)) {
			distComp2Chave = (Float)ferrovia.consultaAtributo(idTrechoComp2, TipoAtributo.COMPRIMENTO) - (Float)ferrovia.consultaAtributo(idComp2, TipoAtributo.POSICAO_ATUAL);
		} else {
			distComp2Chave = (Float)ferrovia.consultaAtributo(idComp2, TipoAtributo.POSICAO_ATUAL);
		}
		
		t1 = u.calculaTempoChegadaAB(velAtualComp1, distComp1Chave);
		t2 = u.calculaTempoChegadaAB(velAtualComp2, distComp2Chave);
		
		if(t1 < t2) {
			return -1;
		} else if(t1 > t2){
			return 1;
		}
		
		
		return 0;
	}
	
	
	public void testeSemParametros(){
		System.out.println("----teste sem param");
	}

	// teste
	public void testeComParametros(String param1, String param2){
		System.out.println("Primeiro param "+param1);
		System.out.println("Segundo param "+param2);
	}
	
}
